package com.ziroom.crm.mq.rabbit.spring.core;

import com.alibaba.fastjson.JSON;
import com.ziroom.crm.mq.core.MqType;
import com.ziroom.crm.mq.core.config.MqConfig;
import com.ziroom.crm.mq.core.resend.ReSend;
import com.ziroom.crm.mq.core.support.ProcessorInvokerDelegate;
import com.ziroom.crm.mq.rabbit.spring.data.RabbitMessage;
import com.ziroom.crm.mq.rabbit.spring.resolve.RabbitResolve;
import com.ziroom.crm.mq.rabbit.spring.wrapper.RabbitSendQueueWrapper;
import com.ziroom.crm.rock.spring.util.SpringContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;

import java.nio.charset.Charset;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * <p></p>
 * <p>
 * <PRE>
 * <BR>    修改记录
 * <BR>-----------------------------------------------
 * <BR>    修改日期         修改人          修改内容
 * </PRE>
 *
 * @author WeiShaoying
 * @version 1.0
 * @date Created in 2020年09月01日 15:03
 * @since 1.0
 */
@Slf4j
public class RabbitMqReSend implements ReSend<RabbitMessage> {

    private static final AtomicBoolean INITIALIZED = new AtomicBoolean(false);

    private RabbitTemplate rabbitTemplate;

    private ProcessorInvokerDelegate facade;

    @Override
    public MqType getType() {
        return MqType.RABBIT;
    }

    @Override
    public void reSend(RabbitMessage rabbitMessage) {
        init();
        RabbitSendQueueWrapper rabbitQueueWrapper = RabbitResolve.buildSendQueueWrapper(rabbitMessage);

        //执行前置处理
        facade.preReSendInvoke(rabbitQueueWrapper, rabbitMessage);

        MessageProperties messageProperties = JSON.parseObject(rabbitMessage.getMessageProperties(), MessageProperties.class);
        byte[] body = rabbitMessage.getMessageBody().getBytes(Charset.forName(MqConfig.charset()));

        Message message = new Message(body, messageProperties);
        // 设置retryCount，让下游知道来源与持久化重试逻辑，以及当前重试次数
        RabbitResolve.setResendCount(message, rabbitMessage.getRetryCount());

        try {
            rabbitTemplate.send(rabbitMessage.getExchange(), rabbitMessage.getRoutingKey(), message, null);
        } catch (Exception e) {
            log.error("[crm-mq]重新发送失败,messageId:{}", rabbitMessage.getId(), e);
            rabbitMessage.setException(e);
        } finally {
            facade.postReSendInvoke(rabbitQueueWrapper, rabbitMessage);
        }
    }

    private void init() {
        if (!INITIALIZED.compareAndSet(false, true)) {
            return;
        }
        rabbitTemplate = SpringContextUtils.getBean(RabbitTemplate.class);
        facade = SpringContextUtils.getBean(ProcessorInvokerDelegate.class);
    }
}
